package com.example.iwalk.newprintapplication.activity;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.TextView;

import com.example.iwalk.newprintapplication.R;
import com.example.iwalk.newprintapplication.imp.BlueToothSocket;
import com.example.iwalk.newprintapplication.imp.NetSocket;
import com.example.iwalk.newprintapplication.imp.Printer58Imp;
import com.example.iwalk.newprintapplication.imp.Printer80Imp;
import com.example.iwalk.newprintapplication.imp.PrinterImp;
import com.example.iwalk.newprintapplication.inter.Printer;
import com.example.iwalk.newprintapplication.inter.SocketInter;
import com.example.iwalk.newprintapplication.inter.SocketStateChangeListener;
import com.example.iwalk.newprintapplication.util.BluetoothPrintFormatUtil;
import com.example.iwalk.newprintapplication.util.BytesUtil;
import com.example.iwalk.newprintapplication.util.ESCUtil;
import com.example.iwalk.newprintapplication.util.TextFormatUtil;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.LinkedHashMap;
import java.util.LinkedList;

import static com.example.iwalk.newprintapplication.constant.SocketState.ERROR_0;
import static com.example.iwalk.newprintapplication.constant.SocketState.ERROR_1;
import static com.example.iwalk.newprintapplication.constant.SocketState.ERROR_2;
import static com.example.iwalk.newprintapplication.constant.SocketState.ERROR_3;
import static com.example.iwalk.newprintapplication.constant.SocketState.ERROR_4;
import static com.example.iwalk.newprintapplication.constant.SocketState.ERROR_5;
import static com.example.iwalk.newprintapplication.constant.SocketState.STATE_1;
import static com.example.iwalk.newprintapplication.constant.SocketState.STATE_2;
import static com.example.iwalk.newprintapplication.constant.SocketState.STATE_3;
import static com.example.iwalk.newprintapplication.constant.SocketState.STATE_4;
import static com.example.iwalk.newprintapplication.constant.SocketState.STATE_5;
import static com.example.iwalk.newprintapplication.imp.PrinterImp.isChinese;
import static com.example.iwalk.newprintapplication.inter.Printer.TYPE_58;
import static com.example.iwalk.newprintapplication.inter.Printer.TYPE_80;

public class PrintActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String CHARSET = "gbk";
    private TextView tv_socket_info;
    private EditText et_content;
    private RadioButton rb_58;
    private RadioButton rb_80;
    private RadioButton rb_left;
    private RadioButton rb_center;
    private RadioButton rb_right;
    private RadioGroup rg_align;
    private TextView tv_right_sp;
    private SeekBar sb_right_sp;
    private int right_sp = 0;
    private RadioGroup rg_type;
    private int type = TYPE_58;
    private int socketType = SocketInter.TYPE_BLUETOOTH;
    private EditText et_qr_content, et_line_sp;
    private RadioButton rb_qr_error_l, rb_qr_error_m, rb_qr_error_q, rb_qr_error_h;
    SocketStateChangeListener stateChangeListener = new SocketStateChangeListener() {
        @Override
        public void onStateChanged(final int state) {
            tv_socket_info.post(new Runnable() {
                @Override
                public void run() {
                    switch (state) {
                        case STATE_1:
                            tv_socket_info.setText("正在创建Socket连接");
                            break;
                        case STATE_2:
                            tv_socket_info.setText("正在获取输出流");
                            break;
                        case STATE_3:
                            tv_socket_info.setText("正在写入测试页面数据");
                            break;
                        case STATE_4:
                            tv_socket_info.setText("正在关闭输出流");
                            break;
                        case STATE_5:
                            tv_socket_info.setText("正在获取输入流");
                            break;
                    }
                }
            });
        }

        @Override
        public void onConnectFailed(final int error) {
            tv_socket_info.post(new Runnable() {
                @Override
                public void run() {
                    switch (error) {
                        case ERROR_0:
                            tv_socket_info.setText("必要参数不能为空");
                            break;
                        case ERROR_1:
                            tv_socket_info.setText("创建Socket失败");
                            break;
                        case ERROR_2:
                            tv_socket_info.setText("获取输出流失败");
                            break;
                        case ERROR_3:
                            tv_socket_info.setText("写入测试页面数据失败");
                            break;
                        case ERROR_4:
                            tv_socket_info.setText("关闭Socket出错");
                            break;
                        case ERROR_5:
                            tv_socket_info.setText("获取输出流失败");
                            break;
                    }
                }
            });
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_print);

        initView();
    }

    private void initView() {
        rg_align = ((RadioGroup) findViewById(R.id.rg_align));
        rg_type = ((RadioGroup) findViewById(R.id.rg_type));
        rg_type.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int i) {
                switch (i) {
                    case R.id.rb_58:
                        type = TYPE_58;
                        break;
                    case R.id.rb_80:
                        type = TYPE_80;
                        break;
                }
            }
        });
        rb_58 = (RadioButton) findViewById(R.id.rb_58);
        rb_80 = (RadioButton) findViewById(R.id.rb_80);
        rb_left = (RadioButton) findViewById(R.id.rb_left);
        rb_center = (RadioButton) findViewById(R.id.rb_center);
        rb_right = (RadioButton) findViewById(R.id.rb_right);
        rb_qr_error_l = ((RadioButton) findViewById(R.id.rb_qr_error_l));
        rb_qr_error_m = ((RadioButton) findViewById(R.id.rb_qr_error_m));
        rb_qr_error_q = ((RadioButton) findViewById(R.id.rb_qr_error_q));
        rb_qr_error_h = ((RadioButton) findViewById(R.id.rb_qr_error_h));
        et_content = (EditText) findViewById(R.id.et_content);
        et_qr_content = ((EditText) findViewById(R.id.et_qr_content));
        et_line_sp = ((EditText) findViewById(R.id.et_line_sp));
        Button btn_net_print = (Button) findViewById(R.id.btn_net_print);
        Button btn_bt_print = (Button) findViewById(R.id.btn_bt_print);
        Button btn_blank_paper = (Button) findViewById(R.id.btn_blank_paper);
        Button btn_cut_paper = (Button) findViewById(R.id.btn_cut_paper);
        Button btn_bt_warp_print = (Button) findViewById(R.id.btn_bt_wrap_print);
        Button btn_bitmap_print = (Button) findViewById(R.id.btn_bt_bitmap_print);
        Button btn_bt_align_print = (Button) findViewById(R.id.btn_bt_align_print);
        Button btn_net_catch = (Button) findViewById(R.id.btn_net_catch_print);
        tv_socket_info = ((TextView) findViewById(R.id.tv_socket_info));
        tv_right_sp = ((TextView) findViewById(R.id.tv_right_sp));
        sb_right_sp = ((SeekBar) findViewById(R.id.sb_right_sp));
        sb_right_sp.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
                tv_right_sp.setText("字符右间距：" + i);
                right_sp = i;
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
        rb_left.setChecked(true);
        rb_58.setChecked(true);
        btn_net_print.setOnClickListener(this);
        btn_bt_print.setOnClickListener(this);
        btn_blank_paper.setOnClickListener(this);
        btn_cut_paper.setOnClickListener(this);
        btn_bt_warp_print.setOnClickListener(this);
        btn_bitmap_print.setOnClickListener(this);
        btn_bt_align_print.setOnClickListener(this);
        btn_net_catch.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_net_print:
                socketType = SocketInter.TYPE_NET;
                NetPrintThreadStart("192.168.31.222");
                break;
            case R.id.btn_bt_print:
                socketType = SocketInter.TYPE_BLUETOOTH;
                BlueToothSocket bluetoothSocket1 = new BlueToothSocket(this, stateChangeListener);
                OutputStream socketOut1 = bluetoothSocket1.getSocketOut();
                try {
                    socketOut1.write(getData());
                    if (socketOut1 == null) {
                        return;
                    }
                    socketOut1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.btn_blank_paper:
                socketType = SocketInter.TYPE_BLUETOOTH;
                BlueToothSocket bluetoothSocket2 = new BlueToothSocket(this, stateChangeListener);
                try {
                    OutputStream socketOut2 = bluetoothSocket2.getSocketOut();
                    socketOut2.write(ESCUtil.nextLine(3));
                    if (socketOut2 == null) {
                        return;
                    }
                    socketOut2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.btn_cut_paper://半切
                socketType = SocketInter.TYPE_BLUETOOTH;
                BlueToothSocket bluetoothSocket3 = new BlueToothSocket(this, stateChangeListener);
                OutputStream socketOut3 = bluetoothSocket3.getSocketOut();
                try {
                    socketOut3.write(ESCUtil.feedPaperCutPartial());
                    if (socketOut3 != null) {
                        socketOut3.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.btn_bt_wrap_print:
                socketType = SocketInter.TYPE_BLUETOOTH;
                Printer printer = type == TYPE_58 ? new Printer58Imp() : new Printer80Imp();
                BlueToothSocket bluetoothSocket4 = new BlueToothSocket(this, stateChangeListener);
                OutputStream socketOut4 = bluetoothSocket4.getSocketOut();
                try {
                    printer.print(socketOut4, getWrapData(printer), stateChangeListener);
                    if (socketOut4 != null) {
                        socketOut4.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.btn_bt_bitmap_print:
                socketType = SocketInter.TYPE_BLUETOOTH;
                Printer printer1 = type == TYPE_58 ? new Printer58Imp() : new Printer80Imp();
                BlueToothSocket bluetoothSocket5 = new BlueToothSocket(this, stateChangeListener);
                OutputStream socketOut5 = bluetoothSocket5.getSocketOut();
                try {
                    printer1.print(socketOut5, getBitmapData(printer1), stateChangeListener);
                    if (socketOut5 != null) {
                        socketOut5.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.btn_bt_align_print:
                socketType = SocketInter.TYPE_BLUETOOTH;
                Printer printer2 = type == TYPE_58 ? new Printer58Imp() : new Printer80Imp();
                BlueToothSocket bluetoothSocket6 = new BlueToothSocket(this, stateChangeListener);
                OutputStream socketOut6 = bluetoothSocket6.getSocketOut();
                try {
                    printer2.print(socketOut6, getAlignData(printer2), stateChangeListener);
                    if (socketOut6 != null) {
                        socketOut6.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case R.id.btn_net_catch_print:
                startActivity(new Intent(this, IpCatcherActivity.class));
                break;
        }
    }

    private void NetPrintThreadStart(final String host) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                SocketInter socketInter =
                        new NetSocket(host, 9100, stateChangeListener);
                Printer printer = new Printer80Imp();
                try {
                    printer.print(socketInter.getSocketOut(), getAlignData(printer), stateChangeListener);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                socketInter.close();
            }
        }).start();
    }

    private byte[] getData() {
        try {
            byte[] next2Line = ESCUtil.nextLine(2);

            byte[] align = new byte[3];
            if (rb_left.isChecked()) {
                align = ESCUtil.alignLeft();
            } else if (rb_center.isChecked()) {
                align = ESCUtil.alignCenter();
            } else if (rb_right.isChecked()) {
                align = ESCUtil.alignRight();
            }

            byte[] rightSp = ESCUtil.setRightSp(right_sp);

            String data = et_content.getText().toString();
            if ("".equals(data)) {
                data = "出餐单万通中心店出餐单万通中心店";
            }
            byte[] content = data.getBytes(CHARSET);
            return ESCUtil.byteMerger(new byte[][]{
                    ESCUtil.init_printer(), align, rightSp,
                    ESCUtil.setLineSp(Integer.parseInt(et_line_sp.getText().toString().equals("")
                            ? "0" : et_line_sp.getText().toString())), content});
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    private byte[] getWrapData(Printer printer) {
        try {
            byte[] align = new byte[3];
            if (rb_left.isChecked()) {
                align = ESCUtil.alignLeft();
            } else if (rb_center.isChecked()) {
                align = ESCUtil.alignCenter();
            } else if (rb_right.isChecked()) {
                align = ESCUtil.alignRight();
            }

            byte[] rightSp = ESCUtil.setRightSp(right_sp);

            byte[] content = getContent(printer);

            byte[] divider = getDividerLine(printer);

            byte[] qrCode = getQrCodeData(printer);

            return ESCUtil.byteMerger(
                    new byte[][]{ESCUtil.init_printer(), ESCUtil.nextLine(2),
                            align, rightSp, content, ESCUtil.nextLine(1), divider,
                            ESCUtil.alignLeft(), qrCode});
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }


    /**
     * 打印排版数据
     *
     * @param printer
     * @return
     * @throws UnsupportedEncodingException
     */
    public byte[] getAlignData(Printer printer) throws UnsupportedEncodingException {
        String alignString = getAlignString(printer);
        byte[] title = "星光大道店铺\n".getBytes(CHARSET);
        byte[] threeData4 = alignString.getBytes(CHARSET);
        byte[] threeData5 = getAlignStrByLine(printer).getBytes(CHARSET);
        byte[] threeData6 = getAlignStrByLine2(printer).getBytes(CHARSET);
        byte[] threeData7 = getAlignStrByLine3(printer).getBytes(CHARSET);
        byte[] threeData8 = "一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十".getBytes(CHARSET);
        byte[] endData = socketType == SocketInter.TYPE_NET ? ESCUtil.feedPaperCutPartial() : ESCUtil.nextLine(2);
        return ESCUtil.byteMerger(
                new byte[][]{ESCUtil.init_printer(),
                        ESCUtil.setLineSp(0),
//                        ESCUtil.boldOn(),
                        ESCUtil.fontSizeSetBig(2),
                        ESCUtil.alignCenter(),
                        title,
                        ESCUtil.fontSizeSetBig(1),
                        getDividerLine2(printer),
//                        ESCUtil.nextLine2(2),//因为前段文字不够填满一行，所以需要打印两个换行符
//                        twoData, ESCUtil.nextLine(1),
//                        threeData, ESCUtil.nextLine(1),
//                        threeData2, ESCUtil.nextLine(1),
                        ESCUtil.fontSizeSetBig(2),
                        ESCUtil.alignLeft(),
                        threeData5,
                        ESCUtil.fontSizeSetBig(1),
                        ESCUtil.nextLine2(1),
                        ESCUtil.boldOff(),
                        ESCUtil.fontSizeSetBig(1),
                        threeData6,
                        threeData7,
                        getDividerLine2(printer), ESCUtil.nextLine2(1),
                        getBitmapData(printer), ESCUtil.nextLine2(1),
                        getQrCodeData(printer), ESCUtil.nextLine2(1),
                        threeData8, ESCUtil.nextLine2(1), endData});
    }

    public byte[] getBitmapData(Printer printer) {
        byte[] align = new byte[3];
        if (rb_left.isChecked()) {
            align = ESCUtil.alignLeft();
        } else if (rb_center.isChecked()) {
            align = ESCUtil.alignCenter();
        } else if (rb_right.isChecked()) {
            align = ESCUtil.alignRight();
        }

        Bitmap bitmap = ESCUtil.
                compressPic(BitmapFactory.decodeResource(getResources(), R.mipmap.test),
                        printer.getDrawableMaxWidth() / 2, printer.getDrawableMaxWidth() / 2);
//                        288, 288);
        boolean needLF = socketType == SocketInter.TYPE_NET ? true : false;
        byte[] bitmapData = ESCUtil.draw2PxPoint(bitmap, needLF);
//        byte[] bitmapData =  ESCUtil.draw2PxPoint(BitmapFactory.decodeResource(getResources(), R.mipmap.test), needLF);

        return ESCUtil.byteMerger(
                new byte[][]{ESCUtil.init_printer(), ESCUtil.nextLine(2),
                        align, ESCUtil.setLineSp(0), bitmapData});
    }

    public byte[] getQrCodeData(Printer printer) {
        String qr_data = et_qr_content.getText().toString();
        if (qr_data.equals("")) {
            qr_data = "http://www.baidu.com";
        }
        return BytesUtil.getZXingQRCode(
                qr_data, printer.getDrawableMaxWidth() / 2);
    }

    public byte[] getDividerLine(Printer printer) throws UnsupportedEncodingException {
        int lineWidth = printer.getLineWidth();
        String blackLine = "";
        for (int i = 0; i < lineWidth; i++) {
            blackLine += "─";
        }
        return blackLine.getBytes(CHARSET);
    }

    public byte[] getDividerLine2(Printer printer) throws UnsupportedEncodingException {
        int lineWidth = printer.getLineWidth();
        String blackLine = "";
        for (int i = 0; i < lineWidth; i++) {
            blackLine += "--";
        }
        return blackLine.getBytes(CHARSET);
    }

    public byte[] getContent(Printer printer) throws UnsupportedEncodingException {
        String data1 = "星级美食（套餐）×1";
        String data2 = "￥88.88";
        int stringWidth = getStringWidth(data1 + data2);
        int stringWidth1 = PrinterImp.String_length(data1 + data2);
        Log.e("sdj", "=========stringWidth:" + stringWidth);
        Log.e("sdj", "=========stringWidth1:" + stringWidth1);
        int needEmptys = printer.getLineStringWidth(0)
                - stringWidth % printer.getLineStringWidth(0);
        String emptys = "";
        while (needEmptys > 0) {
            emptys += " ";
            needEmptys -= 1;
        }
        return (data1 + emptys + data2).getBytes(CHARSET);
    }

    public int getStringWidth(String str) {
        int width = 0;
        for (char c : str.toCharArray()) {
            width += isChinese(c) ? 2 : 1;
            Log.e("sdj", "-------" + isChinese(c));
        }
        return width;
    }

    public static String getAlignString(Printer printer) {
        StringBuilder sb = new StringBuilder();
        //排版标题
        sb.append(BluetoothPrintFormatUtil.printTitle("订餐单\n"))
                .append("日期：2013-06-25\n");

        //排版People信息
        LinkedHashMap<String, String> leftMsgMap = new LinkedHashMap<>();
        LinkedHashMap<String, String> rightMsgMap = new LinkedHashMap<>();

        leftMsgMap.put("姓名", "Aaron_lin");
        leftMsgMap.put("病区", "11脑外科");
        leftMsgMap.put("床号", "123");
        leftMsgMap.put("性别", "女");

        rightMsgMap.put("住院号", "2112\n");
        rightMsgMap.put("年龄", "22\n");
        rightMsgMap.put("身高", "175cm\n");
        rightMsgMap.put("BMI", "22.0\n");
        sb.append(BluetoothPrintFormatUtil.printSymmetryMSG(leftMsgMap, rightMsgMap));

        //排版点餐菜单信息  必须以 '$' 分隔菜单    格式是     菜谱名$数量$单价
        LinkedHashMap<String, LinkedList<String>> menuMsgMap = new LinkedHashMap<>();
        LinkedList<String> menuList = new LinkedList<>();
        menuList.add(" 红烧鸭块$2$22.0");
        menuList.add(" 水煮鱼片$1$25.0");
        menuMsgMap.put("早餐", menuList);

        menuList.clear();
        menuList.add(" 农家小炒肉$1$18.0");
        menuList.add(" 鱼香肉丝1$2$18.0");
        menuList.add(" 炒饭$1$18.0");
        menuMsgMap.put("午餐", menuList);

        menuList.clear();
        menuList.add(" 红烧鸡块$1$10.0");
        menuMsgMap.put("晚餐", menuList);
        sb.append(TextFormatUtil.printMenuMSG(menuMsgMap, printer.getLineStringWidth(0)))
                .append("总计：111.0\n")
                .append("打印日期：2013-06-20\n\n\n");

        return sb.toString();
    }

    /**
     * 四等分四列，加空格来分隔两列
     *
     * @param printer
     * @return
     */
    public static String getAlignStrByLine(Printer printer) {
        int lineStringWidth = printer.getLineStringWidth(1);
        TextFormatUtil.addLineElement("项目", lineStringWidth / 4 - 1, 1);
        TextFormatUtil.addLineElement("", 1, 1);//当字段过长时，加空格来分隔两列
        TextFormatUtil.addLineElement("单价", lineStringWidth / 4 - 1, 2);
        TextFormatUtil.addLineElement("", 1, 1);
        TextFormatUtil.addLineElement("数量", lineStringWidth / 4 - 1, 2);
        TextFormatUtil.addLineElement("", 1, 1);
        TextFormatUtil.addLineElement("总计", lineStringWidth / 4, 2);
        return TextFormatUtil.endLine(lineStringWidth);
    }

    public static String getAlignStrByLine2(Printer printer) {
        int lineStringWidth = printer.getLineStringWidth(0);
        TextFormatUtil.addLineElement("大宝健123大abc宝健大宝健:", lineStringWidth / 4 - 1, 0);
        TextFormatUtil.addLineElement("", 1, 1);
        TextFormatUtil.addLineElement("60.0000000", lineStringWidth / 4 - 1, 2);
        TextFormatUtil.addLineElement("", 1, 1);
        TextFormatUtil.addLineElement("2000000000", lineStringWidth / 4 - 1, 2);
        TextFormatUtil.addLineElement("", 1, 1);
        TextFormatUtil.addLineElement("120.000000000000000", lineStringWidth / 4, 2);
        return TextFormatUtil.endLine(printer.getLineStringWidth(0));
    }

    public static String getAlignStrByLine3(Printer printer) {
        int lineStringWidth = printer.getLineStringWidth(0);
        TextFormatUtil.addLineElement("大宝健大宝健大宝健:", lineStringWidth / 4 - 1, 0);
        TextFormatUtil.addLineElement("", 1, 1);
        TextFormatUtil.addLineElement("60.0000000", lineStringWidth / 4 - 1, 2);
        TextFormatUtil.addLineElement("", 1, 1);
        TextFormatUtil.addLineElement("2000000000", lineStringWidth / 4 - 1, 2);
        TextFormatUtil.addLineElement("", 1, 1);
        TextFormatUtil.addLineElement("120.000000000000000", lineStringWidth / 4, 2);
        return TextFormatUtil.endLine(printer.getLineStringWidth(0));
    }
}
